package com.desuntech.modules
{
	import C4D.kbmMWConnection;
	import C4D.kbmMWEvent;
	import C4D.kbmMWQuery;
	import C4D.kbmMWResponse;
	import C4D.kbmMWRow;
	
	import com.desuntech.modules.components.ModuleGroup;
	import com.desuntech.modules.events.CRUDEvent;
	import com.desuntech.modules.events.PagerEvent;
	import com.desuntech.modules.events.QueryEvent;
	import com.desuntech.utils.DataGrid2ExcelUtil;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.core.FlexGlobals;
	import mx.events.CloseEvent;
	import mx.managers.PopUpManager;
	
	import spark.components.DataGrid;
	import spark.modules.Module;
	
	[Event(name="addPopup", type="com.desuntech.modules.events.PopupEvent")]
	[Event(name="removePopup", type="com.desuntech.modules.events.PopupEvent")]
	[Event(name="showPhoto", type="com.desuntech.modules.events.PopupEvent")]
	
	public class CommonModule extends Module
	{
		protected var _conn:kbmMWConnection;
		private var _q:Object = new Object();
		protected var _popup:Object = new Object();
		private var _content:Object = new Object();
		private var _sql:Object = new Object();
		private var _staticWhereConditions:Object = new Object();
		private var _whereConditions:Object = new Object();
		protected var _currentView:String;
		protected var _currentTable:String;
		protected var _currentQueryAllTable:String;
		protected var _currentQueryAllView:String;
		protected var _queryAllItems:Array;
		protected var _dbKind:String;
		private var _searchResultHandler:Function;
		protected var _forceFirstPage:Boolean;
		protected var _deleteIndex:int;
		
		public function CommonModule()
		{
			super();
		}
		
		public function set connection(conn:kbmMWConnection):void
		{
			_conn = conn;
		}
		
		public function set dbKind(value:String):void {
			_dbKind = value;
		}
		
		// search
		protected function search(e:QueryEvent):void {
			_currentView = e.view;
			_currentTable = e.table;
			whereConditions = '';
			if(staticWhereConditions) {
				whereConditions = staticWhereConditions;
				if(e.conditions) whereConditions += ' AND ';
			}
			if(e.conditions) whereConditions += e.conditions;
			_forceFirstPage = true;
			queryCount();
		}
		
		protected function searchAll(table:String, conditions:String, view:String, resultHandler:Function):void {
			_currentView = view;
			_searchResultHandler = resultHandler;
			if(!altQuery) altQuery = new kbmMWQuery();
			altQuery.addEventListener(kbmMWEvent.QueryDataAvailableEvent, SearchCall_ResultHandler);
			altQuery.addEventListener(kbmMWEvent.FailureEvent, SearchCall_FailureHandler);
			altQuery.Connection = _conn;
			var s:String = 'SELECT * FROM ' + table;
			if(conditions){
				s += ' WHERE ' + conditions;
			}
			altQuery.Query = s;
			altQuery.Open();
		}
		
		private function SearchCall_ResultHandler(event:Event):void {
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.QueryDataAvailableEvent, SearchCall_ResultHandler);
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.FailureEvent, SearchCall_FailureHandler);
			
			_searchResultHandler(new ArrayCollection((event.target as kbmMWQuery).Rows.slice()));
		}
		
		// query all
		protected function queryAll(items:Array):void {
			_queryAllItems = items;
			queryAllNext();
		}
		
		private function queryAllNext():void {
			if(_queryAllItems[0]) {
				_currentQueryAllTable = _queryAllItems[0]['table'];
				_currentQueryAllView =  _queryAllItems[0]['view'];
				if(!altQuery) altQuery = new kbmMWQuery();
				altQuery.addEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryAllCall_ResultHandler);
				altQuery.addEventListener(kbmMWEvent.FailureEvent, QueryAllCall_FailureHandler);
				altQuery.Connection = _conn;
				var s:String = '';
				if(_queryAllItems[0]['distinct']) {
					s = 'SELECT DISTINCT ' + _queryAllItems[0]['distinct'] +' FROM ' + _currentQueryAllTable;
				} else {
					s = 'SELECT * FROM ' + _currentQueryAllTable;
				}
				if(_queryAllItems[0]['where']){
					s += ' WHERE ' + _queryAllItems[0]['where'];
				}
				altQuery.Query = s;
				altQuery.Open();
			}
		}
		
		private function QueryAllCall_ResultHandler(event:Event):void {
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryAllCall_ResultHandler);
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.FailureEvent, QueryAllCall_FailureHandler);
			
			setCBData(new ArrayCollection((event.target as kbmMWQuery).Rows.slice()));
			_queryAllItems.shift();
			queryAllNext();
		}
		
		// should be overrided
		protected function setCBData(ac:ArrayCollection):void {
			
		}
		
		// add conditions to sql
		private function addConditions(value:String):String {
			if(whereConditions) value += ' WHERE ' + whereConditions;
			return value;
		}
		
		// query count
		protected function queryCount():void
		{
			openQuery(addConditions('SELECT COUNT(*) as XCOUNT FROM ' + _currentTable), true);
		}
		
		protected function openQuery(sql:String, selectCount:Boolean = false):void {
			if(selectCount) {
				query.addEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryCountCall_ResultHandler);
				query.addEventListener(kbmMWEvent.FailureEvent, QueryCountCall_FailureHandler);
			} else {
				query.addEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryCall_ResultHandler);
				query.addEventListener(kbmMWEvent.FailureEvent, QueryCall_FailureHandler);
			}
			query.Connection = _conn;
			query.Query = sql;
			query.Open();
		}
		
		private function QueryCountCall_ResultHandler(event:Event):void {
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryCountCall_ResultHandler);
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.FailureEvent, QueryCountCall_FailureHandler);
			
			totalCount = (event.target as kbmMWQuery)[0]['XCOUNT'];
			calculatePagesAndRequery();
		}
		
		private function calculatePagesAndRequery():void {
			totalPage = Math.ceil(totalCount/countPerpage);
			if(totalCount == 0) {
//				Alert.show('查询结果为空','提示');
				sql = addConditions('SELECT * FROM ' + _currentTable);
				openQuery(sql);
				currentPage = 0;
			} else {
				if(currentPage == 0) currentPage = 1;
				if(_forceFirstPage) currentPage = 1;
				sql = getLimitSQL();
				openQuery(sql);
			}
		}
		
		private function getLimitSQL():String {
			var result:String;
			switch(_dbKind) {
				case 'MYSQL':
					result = 'SELECT * FROM ' + _currentTable;
					result = addConditions(result);
					result += ' LIMIT ' + (currentPage-1)*countPerpage + ', ' + countPerpage;
					break;
				case 'SQLSERVER':
//					SELECT TOP 6 * FROM jcjg_user where AutoId not in (SELECT TOP 0 AutoId FROM jcjg_user)
					result = 'SELECT TOP ' + countPerpage + ' * FROM ' + _currentTable;
					result = addConditions(result);
					if(whereConditions) {
						result += ' AND ';
					} else {
						result += ' WHERE ';
					}
					result += KeyField + ' not in (';
					result += 'SELECT TOP ' + (currentPage-1)*countPerpage + ' ' + KeyField + ' FROM ' + _currentTable;
					result = addConditions(result);
					result += ')';
					break;
			}
			return result;
		}
		
		private function QueryCall_ResultHandler(event:Event):void {
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryCall_ResultHandler);
			(event.target as kbmMWQuery).removeEventListener(kbmMWEvent.FailureEvent, QueryCall_FailureHandler);
			dgTest.dataProvider = new ArrayCollection((event.target as kbmMWQuery).Rows);
			_forceFirstPage = false;
		}
		
		// failure handlers
		private function SearchCall_FailureHandler(event:Event):void {
			var q:kbmMWQuery = event.target as kbmMWQuery;
			q.removeEventListener(kbmMWEvent.QueryDataAvailableEvent, SearchCall_ResultHandler);
			q.removeEventListener(kbmMWEvent.FailureEvent, SearchCall_FailureHandler);
			var result:kbmMWResponse;
			result = (event as kbmMWEvent).resultObject as kbmMWResponse;
			Alert.show("Query failure:"+result.header.StatusText+"\n"); 
		}
		
		private function QueryCall_FailureHandler(event:Event):void {
			var q:kbmMWQuery = event.target as kbmMWQuery;
			q.removeEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryCall_ResultHandler);
			q.removeEventListener(kbmMWEvent.FailureEvent, QueryCall_FailureHandler);
			var result:kbmMWResponse;
			result = (event as kbmMWEvent).resultObject as kbmMWResponse;
			Alert.show("Query failure:"+result.header.StatusText+"\n"); 
			_forceFirstPage = false;
		}
		
		private function QueryCountCall_FailureHandler(event:Event):void {
			var q:kbmMWQuery = event.target as kbmMWQuery;
			q.removeEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryCountCall_ResultHandler);
			q.removeEventListener(kbmMWEvent.FailureEvent, QueryCountCall_FailureHandler);
			var result:kbmMWResponse;
			result = (event as kbmMWEvent).resultObject as kbmMWResponse;
			Alert.show("Query failure:"+result.header.StatusText+"\n"); 
		}
		
		private function QueryAllCall_FailureHandler(event:Event):void {
			var q:kbmMWQuery = event.target as kbmMWQuery;
			q.removeEventListener(kbmMWEvent.QueryDataAvailableEvent, QueryAllCall_ResultHandler);
			q.removeEventListener(kbmMWEvent.FailureEvent, QueryAllCall_FailureHandler);
			var result:kbmMWResponse;
			result = (event as kbmMWEvent).resultObject as kbmMWResponse;
			Alert.show("Query failure:"+result.header.StatusText+"\n"); 
		}
		
		// item actions
		// CREAT
		protected function beginInsertItem(event:CRUDEvent):void
		{
			_currentTable = event.table;
			_currentView = event.view;
			popup.index = event.index;
			popup.action = CRUDEvent.INSERT;
			popup.addEventListener(CloseEvent.CLOSE, closeTW);
			popup.addEventListener(CRUDEvent.INSERT, insertItem);
				
			PopUpManager.addPopUp(popup, FlexGlobals.topLevelApplication as DisplayObject, true);
			PopUpManager.centerPopUp(popup);
		}
		
		protected function insertItem(e:CRUDEvent):void {
			query.TableNames = _currentTable;
			query.KeyFields = KeyField;
			var _row:kbmMWRow = e.target.item;
			query.addItem(_row);
			
			query.Resolve(onInsertSuccess, onResolveFailed);
		}
		
		private function onInsertSuccess(o:Object):void {
			popup.close();
			queryCount();
		}
		
		protected function onResolveFailed(o:Object):void {
			Alert.show(o.toString(), '操作失败');
		}
		
		// READ
		private function beginViewItem(event:CRUDEvent):void
		{
			_currentTable = event.table;
			_currentView = event.view;
			popup.index = event.index;
			popup.action = CRUDEvent.VIEW;
			popup.item = dgTest.selectedItem as kbmMWRow;
			popup.addEventListener(CloseEvent.CLOSE, closeTW);
			
			PopUpManager.addPopUp(popup, FlexGlobals.topLevelApplication as DisplayObject, true);
			PopUpManager.centerPopUp(popup);
		}
		
		// UPDATE
		private function beginEditItem(event:CRUDEvent):void
		{
			_currentTable = event.table;
			_currentView = event.view;
			popup.action = CRUDEvent.EDIT;
			popup.item = dgTest.selectedItem as kbmMWRow;
			popup.addEventListener(CloseEvent.CLOSE, closeTW);
			popup.addEventListener(CRUDEvent.EDIT, updateItem);
			
			PopUpManager.addPopUp(popup, FlexGlobals.topLevelApplication as DisplayObject, true);
			PopUpManager.centerPopUp(popup);
		}
		
		private function updateItem(e:CRUDEvent):void {
			query.TableNames = _currentTable;
			query.KeyFields = KeyField;
			query.Resolve(onUpdateSuccess, onResolveFailed);
		}
		
		private function onUpdateSuccess(o:Object):void {
			popup.close();
			repeatLastQuery();
		}
		
		private function repeatLastQuery():void {
			openQuery(sql);
		}
		
		// DELETE
		protected function beginDeleteItem(event:CRUDEvent):void
		{
			_currentTable = event.table;
			_currentView = event.view;
			_deleteIndex = event.index;
			Alert.show('确认删除该条数据？','警告',Alert.OK | Alert.CANCEL, content, doDelete);
		}
		
		private function doDelete(e:CloseEvent):void {
			if (e.detail==Alert.OK) {
				query.TableNames = _currentTable;
				query.KeyFields = KeyField;
				var i:int = _deleteIndex;
				if(i>-1) {
					(query[i] as kbmMWRow).UpdateStatus = kbmMWRow.UPDATESTATUS_DELETED;
					query.Resolve(itemDeleteSuccessHandler, onResolveFailed);
				}
			}
		}
		
		private function itemDeleteSuccessHandler(result:Object):void {
			query.removeItemAt(_deleteIndex);
			queryCount();
		}
		
		private function beginChangePerpage(event:PagerEvent):void
		{
			_currentTable = event.table;
			_currentView = event.view;
			countPerpage = event.value;
			_forceFirstPage = true;
			calculatePagesAndRequery();
		}
		
		private function beginChangePage(event:PagerEvent):void {
			_currentTable = event.table;
			_currentView = event.view;
			var page:int = event.value;
			if(page != currentPage) {
				if(page<1 || page>totalPage) return;
				currentPage = page;
				sql = getLimitSQL();
				openQuery(sql);
			}
		}
		
		// Remove PopUpWindow
		protected function closeTW(evt:CloseEvent):void {
			popup.removeEventListener(CloseEvent.CLOSE, closeTW);
			if(popup.hasEventListener(CRUDEvent.EDIT)) popup.removeEventListener(CRUDEvent.EDIT, updateItem);
			if(popup.hasEventListener(CRUDEvent.INSERT)) popup.removeEventListener(CRUDEvent.INSERT, insertItem);
			
			PopUpManager.removePopUp(popup);
			popup = null;
		}
		
		// actions after datagrid item was selected
		private function onSelectionChange(event:Event):void
		{
			/* var item:kbmMWRow = dgTest.selectedItem as kbmMWRow;
			var imgSrc:BitmapData;
			if(dgTest.selectedItem['Photo']) {
			var decoder:BMPDecoder = new BMPDecoder();
			imgSrc = decoder.decode(dgTest.selectedItem['Photo']);
			} else {
			imgSrc = null;
			}
			dispatchEvent(new DemoModuleEvent(DemoModuleEvent.SHOW_PHOTO, imgSrc)); */
		}
		
		private function exportToExcel(e:Event):void {
			DataGrid2ExcelUtil.exportToExcel(e.currentTarget.dgTest);
		}
		
		protected function get dgTest():DataGrid {
			return _content[_currentView].dgTest;
		}
		
		protected function set totalPage(value:int):void {
			_content[_currentView].totalPage = value;
		}
		
		protected function get totalPage():int {
			return _content[_currentView].totalPage;
		}
		
		protected function set totalCount(value:int):void {
			_content[_currentView].totalCount = value;
		}
		
		protected function get totalCount():int {
			return _content[_currentView].totalCount;
		}
		
		protected function set countPerpage(value:int):void {
			_content[_currentView].countPerpage = value;
		}
		
		protected function get countPerpage():int {
			return _content[_currentView].countPerpage;
		}
		
		protected function set currentPage(value:int):void {
			_content[_currentView].currentPage = value;
		}
		
		protected function get currentPage():int {
			return _content[_currentView].currentPage;
		}
		
		protected function get content():* {
			return _content[_currentView];
		}
		
		protected function set content(value:*):void {
			_content[_currentView] = value;
		}
		
		protected function get query():kbmMWQuery {
			return _q[_currentView];
		}
		
		protected function set query(value:kbmMWQuery):void {
			_q[_currentView] = value;
		}
		
		protected function get altQuery():kbmMWQuery {
			return _q[AppConstants.ALT_QUERY];
		}
		
		protected function set altQuery(value:kbmMWQuery):void {
			_q[AppConstants.ALT_QUERY] = value;
		}
		
		protected function set sql(value:String):void {
			_sql[_currentView] = value;
		}
		
		protected function get sql():String {
			return _sql[_currentView];
		}
		
		protected function get staticWhereConditions():String {
			return _staticWhereConditions[_currentView];
		}
		
		protected function set staticWhereConditions(value:String):void {
			_staticWhereConditions[_currentView] = value;
			_whereConditions[_currentView] = value;
		}
		
		protected function set popup(value:*):void {
			_popup[_currentView] = value;
		}
		
		protected function addContentCommonELs(content:Object, includeCRUD:Boolean = true, includePageRelated:Boolean = true):void {
			if(includeCRUD) {
				content.addEventListener(CRUDEvent.DELETE, beginDeleteItem);
				content.addEventListener(CRUDEvent.EDIT, beginEditItem);
				content.addEventListener(CRUDEvent.INSERT, beginInsertItem);
				content.addEventListener(CRUDEvent.VIEW, beginViewItem);
				content.addEventListener(ModuleGroup.EXPORT_AS_EXCEL, exportToExcel);
			}
			if(includePageRelated) {
				content.addEventListener(PagerEvent.CHANGE_PAGE, beginChangePage);
				content.addEventListener(PagerEvent.CHANGE_PERPAGE, beginChangePerpage);
				content.addEventListener(ModuleGroup.SELECTION_CHANGED, onSelectionChange);
			}
		}
		
		protected function get whereConditions():String {
			if(_whereConditions[_currentView]) {
				return _whereConditions[_currentView];
			} else {
				return '';
			}
		}
		
		protected function set whereConditions(value:String):void {
			_whereConditions[_currentView] = value;
		}
		
		// following functions should be overrieded
		protected function get popup():* {
		}
		
		protected  function get KeyField():String {
			return '';
		}
	}
}